﻿// MouseStart.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include <iostream>
#include "Listener.h"
#include "Global.h"
#include "CppMouseHandler.cpp"
#include <vector>
#include "easylogging++.h"
#include "Gun.h"
#include "JsonUtil.h"
#include <exception>  
#include <stdexcept> // 对于标准异常
#include "Auth.h"
#include <locale>
#include <codecvt>
#include <iomanip>
#include <sstream>
#include <conio.h>

INITIALIZE_EASYLOGGINGPP

// 全局变量
HWND g_hwnd = NULL;
HBITMAP g_hbmMem = NULL;
HDC g_hdcMem = NULL;

std::atomic<int> version;

// 函数声明
int createViewWindow();
void InitializeBackBuffer();
void CleanupBackBuffer();
void DrawTextOnWindow(const std::wstring& text);
void RedrawWindowContent();
void ClearWindow();
std::wstring StringToWString2(const std::string& str)
{
	std::wstring wstr(str.length(), L' ');
	std::copy(str.begin(), str.end(), wstr.begin());
	return wstr;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);

		// 将缓冲区内容绘制到窗口
		BitBlt(hdc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), g_hdcMem, 0, 0, SRCCOPY);
		EndPaint(hwnd, &ps);
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}

	case WM_DESTROY:
		CleanupBackBuffer();
		PostQuitMessage(0);
		return 0;

	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
}

bool IsKeyLockOn(int vKey) {
	// 使用GetKeyState检测键的toggle状态  
	// 如果最低位被设置，则表示键的toggle状态是ON  
	return (GetKeyState(vKey) & 0x0001) == 0;
}

std::wstring StringToWString(const std::string& str);

int main()
{
	/// 防止Fatal级别日志中断程序
	el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
	/// 选择划分级别的日志	
	el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging);
	/// 设置级别门阀值，修改参数可以控制日志输出
	el::Loggers::setLoggingLevel(el::Level::Info);
	try {
		// LoadSetting
		int loadResult = global_constant.loadSettings();
		if (loadResult == 0)
		{
			LOG(INFO) << "LoadSetting Error!!!";
			return 1;
		}
		bool pass = check(global_constant.uuid);
		if (!pass) {
			MessageBox(0, TEXT("您的软件已经过期，请联系QQ3498156146"), TEXT("过期提醒"), MB_OK);
			return 1;
		}

		// select Mouse instance
		CppMouseHander cpp_mouse_handler;
		MouseHandler* mouse_handler = &cpp_mouse_handler;
		// add listen key
		global_constant.WatchedKeysState[VK_LSHIFT] = false;
		global_constant.WatchedKeysState[WM_LBUTTONDOWN] = false;
		global_constant.WatchedKeysState[WM_LBUTTONUP] = false;
		global_constant.WatchedKeysState[WM_RBUTTONDOWN] = false;
		global_constant.WatchedKeysState[WM_RBUTTONUP] = false;

		// Start listening
		input_listener.StartListening();

		std::thread startWork([mouse_handler] {
			while (!global_constant.exit) {
				global_func.park();
				const auto it = global_constant.gunMap.find(global_constant.gun_setting_select_name);
				if (it == global_constant.gunMap.end()) {
					global_func.delay(10);
					continue;
				}
				Gun gun = it->second;

				bool IsKeyLockOnNumLock = false;
				// 检测Num Lock是否开启  
				if (IsKeyLockOn(VK_NUMLOCK)) {
					IsKeyLockOnNumLock = true;
				}


				if (global_constant.open == 1 && global_constant.WatchedKeysState[WM_LBUTTONDOWN] && !global_constant.WatchedKeysState[WM_LBUTTONUP] && ((global_constant.custom == "fast" && global_constant.WatchedKeysState[WM_RBUTTONDOWN]) || global_constant.custom == "default")) {
					// 记录开始时间点
					std::vector<std::vector<MovementParams>> movementsConcurrent = global_constant.is_complement == 0 ? gun.movements : gun.movementsLong;
					LOG(DEBUG) << "Fire Model " << global_constant.fire_model << " >>>>>>";
					auto start = std::chrono::high_resolution_clock::now();
					for (size_t i = 0; i < movementsConcurrent.size(); i++)
					{
						LOG(DEBUG) << "Fire " << i << " >>>>>>";
						for (const auto& movement : movementsConcurrent[i]) {
							// 记录每次操作的开始时间点
							auto start = std::chrono::high_resolution_clock::now();

							// 模拟移动操作
							mouse_handler->move(IsKeyLockOnNumLock ? 5 : 0, movement.distance, false);

							// 高精度延时
							global_func.delay(movement.interval);

							// 记录每次操作的结束时间点
							auto end = std::chrono::high_resolution_clock::now();

							// 计算每次操作的耗时并输出
							auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

							LOG(DEBUG) << "Index: " << (i + 1) << ", Movement distance: " << movement.distance << ", Movement expect time: " << movement.interval << " ms, Movement time: " << duration.count() << " ms";

						}
						// 判断是否松开鼠标左键
						if (!global_constant.WatchedKeysState[WM_LBUTTONDOWN] && global_constant.WatchedKeysState[WM_LBUTTONUP])
						{
							break;
						}
					}
					// 打完一轮后需要松开一次鼠标左键才能再次执行
					global_constant.WatchedKeysState[WM_LBUTTONDOWN] = false;
					global_constant.WatchedKeysState[WM_LBUTTONUP] = true;
					// 记录结束时间点
					auto end = std::chrono::high_resolution_clock::now();

					// 计算时间差并将结果转换为毫秒
					auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

					// 输出耗时
					LOG(DEBUG) << "Time taken: " << duration.count() << " milliseconds" << std::endl;
				}
				if (global_constant.WatchedKeysState[VK_LSHIFT])
				{
					LOG(DEBUG) << "VK_LSHIFT:" << global_constant.WatchedKeysState[VK_LSHIFT] << std::endl;
				}
			}
			});
		//// 打印提示信息  
		//LOG(INFO) << "按任意键隐藏控制台...";
		//// 等待用户按键  
		//std::cin.get();
		//// 隐藏控制台窗口  
		//ShowWindow(GetConsoleWindow(), SW_HIDE);
		createViewWindow();
		// Stop listening;
		input_listener.StopListening();
	}
	catch (...) {
		// 捕获所有其他类型的异常
		LOG(ERROR) << "Caught an unknown exception.";
	}

	return 0;
}



int createViewWindow()
{
	HINSTANCE hInstance = GetModuleHandle(NULL);

	const wchar_t CLASS_NAME[] = L"Transparent Window Class";

	WNDCLASS wc = { };

	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.lpszClassName = CLASS_NAME;
	wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); // 无背景画刷

	RegisterClass(&wc);

	// 获取屏幕的宽度和高度  
	int screenWidth = GetSystemMetrics(SM_CXSCREEN);
	int screenHeight = GetSystemMetrics(SM_CYSCREEN);

	// 计算四分之一屏幕的宽度和高度  
	int quarterWidth = screenWidth / 4;
	int quarterHeight = screenHeight / 4;

	g_hwnd = CreateWindowEx(
		WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, // 扩展窗口样式
		CLASS_NAME,                     // 窗口类名
		L"Transparent Window",          // 窗口标题
		WS_POPUP,                       // 窗口风格

		// 全屏大小和位置
		0, 0, screenWidth, screenHeight,

		NULL,       // 父窗口
		NULL,       // 菜单
		hInstance,  // 实例句柄
		NULL        // 附加应用程序数据
	);

	if (g_hwnd == NULL)
	{
		printf("Failed to create window\n");
		return 0;
	}

	// 设置窗口透明
	SetLayeredWindowAttributes(g_hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);

	ShowWindow(g_hwnd, SW_SHOW);

	// 初始化缓冲区
	InitializeBackBuffer();

	std::thread printHandGun([] {
		while (true)
		{
			global_func.parkDraw();
			ClearWindow();
			const auto it = global_constant.gunMap.find(global_constant.gun_setting_select_name);
			if (it == global_constant.gunMap.end()) {
				LOG(INFO) << L"未找到枪械";
				continue;
			}
			Gun gun = it->second;
			std::wostringstream oss;
			oss << L"========================" << std::endl;
			oss << L">> 手持枪械: \t" << StringToWString2(gun.name) << std::endl;
			oss << L">> 满配系数: \t" << global_constant.full_magnification << std::endl;
			oss << L">> 裸配系数: \t" << global_constant.low_magnification << std::endl;
			oss << L">> 站姿系数: \t" << global_constant.stand_magnification << std::endl;
			oss << L">> 蹲姿系数: \t" << global_constant.squat_magnification << std::endl;
			oss << L"========================" << std::endl;
			// Display gun name in a stylish format
			//oss << L">> 手持枪械：\t" << StringToWString2(gun.name) << std::endl;
			//	// Display each attachment
			//oss << L">> 瞄准镜：\t" << StringToWString2(gun.muzzle.key) << std::endl;
			//oss << L">> 枪口配件：\t" << StringToWString2(gun.grip.key) << std::endl;
			//oss << L">> 握把：\t" << StringToWString2(gun.sight.key) << std::endl;
			//oss << L">> 枪托：\t" << StringToWString2(gun.butt.key) << std::endl;
			//oss << L"========================" << std::endl;
			std::wstring str = oss.str();
			DrawTextOnWindow(str);
			int currentVersion = ++version;
			std::thread([currentVersion]() {
				// 等待指定的时间
				std::this_thread::sleep_for(std::chrono::milliseconds(5000));
				if (currentVersion == version)
				{
					// 执行回调函数
					ClearWindow();
				}
				}).detach(); // 分离线程使其独立运行
		}

		});

	// 运行消息循环
	MSG msg = { };
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 1;
}

void InitializeBackBuffer()
{
	HDC hdc = GetDC(g_hwnd);
	g_hdcMem = CreateCompatibleDC(hdc);
	g_hbmMem = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
	SelectObject(g_hdcMem, g_hbmMem);
	ReleaseDC(g_hwnd, hdc);
}

void CleanupBackBuffer()
{
	DeleteObject(g_hbmMem);
	DeleteDC(g_hdcMem);
}

void DrawTextOnWindow(const std::wstring& text)
{
	HDC hdc = g_hdcMem;

	// 清除背景
	RECT rect;
	GetClientRect(g_hwnd, &rect);
	FillRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

	// 设置字体
	HFONT hFont = CreateFont(
		24,                         // 字体高度
		0,                          // 字体宽度
		0,                          // 字体的倾斜角度
		0,                          // 基线相对于屏幕的旋转角度
		FW_BOLD,                    // 字体的粗细
		FALSE,                      // 是否为斜体
		FALSE,                      // 是否有下划线
		FALSE,                      // 是否有删除线
		DEFAULT_CHARSET,               // 字符集
		OUT_DEFAULT_PRECIS,         // 输出精度
		CLIP_DEFAULT_PRECIS,        // 剪辑精度
		DEFAULT_QUALITY,            // 输出质量
		DEFAULT_PITCH | FF_SWISS,   // 字体族和间距
		TEXT("宋体"));             // 字体名称

	SelectObject(hdc, hFont);

	// 设置文本颜色
	SetTextColor(hdc, RGB(255, 0, 0)); // 红色

	// 设置背景透明
	SetBkMode(hdc, TRANSPARENT);

	// 绘制文本
	//DrawText(hdc, 50, 50, text.c_str(), text.length());

	// 添加边距
	int margin = 40; // 边距大小
	rect.left += margin;
	rect.top += margin;
	rect.right -= margin;
	rect.bottom -= margin;
	DrawText(hdc, text.c_str(), -1, &rect, DT_LEFT | DT_TOP | DT_WORDBREAK);

	// 释放资源
	DeleteObject(hFont);

	// 强制重绘窗口
	RedrawWindow(g_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}

void RedrawWindowContent()
{
	InvalidateRect(g_hwnd, NULL, FALSE);
}

void ClearWindow()
{
	HDC hdc = g_hdcMem;

	// 清除背景
	RECT rect;
	GetClientRect(g_hwnd, &rect);
	FillRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

	// 强制重绘窗口
	RedrawWindow(g_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}

std::wstring StringToWString(const std::string& str)
{
	if (str.empty())
	{
		return L"";
	}
	int bufferSize = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
	std::wstring wide2(bufferSize, 0);
	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &wide2[0], bufferSize);
	return wide2;
}